package com.zhuqi.dynamic;

import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * Copyright (C) 2014-2016 天津紫藤科技有限公司. Co. Ltd. All Rights Reserved.
 *
 * @author Andy
 * @version v1
 * @description 字符串工具类
 * @utill
 * @module
 * @date 2016年11月25日
 * @code
 */
@Slf4j
public class SignTools {
    /**
     * 返回一个升序排序的树map
     *
     * @return
     */
    public static Map<String, Object> getTreeMap() {
        Map<String, Object> map = new TreeMap<>(
                Comparator.naturalOrder());
        return map;
    }

    /**
     * map转换为字符串
     *
     * @param map
     * @return
     */
    public static String getParamStr(Map<String, Object> map) {
        StringBuffer returnStr = new StringBuffer();
        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            returnStr.append(key + "=" + map.get(key) + "&");
        }
        returnStr.deleteCharAt(returnStr.length() - 1);
        return returnStr.toString();
    }

    /**
     * MD5加密
     *
     * @param data
     * @return
     * @throws Exception
     */
    public static String encryptMD5(String data) throws Exception {

        String reStr = null;
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bytes = md5.digest(data.getBytes());
            StringBuffer stringBuffer = new StringBuffer();
            for (byte b : bytes) {
                int bt = b & 0xff;
                if (bt < 16) {
                    stringBuffer.append(0);
                }
                stringBuffer.append(Integer.toHexString(bt));
            }
            reStr = stringBuffer.toString();
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(),e);
        }
        return reStr.toUpperCase();
    }

    /**
     * 加密map形式的data
     *
     * @param map
     * @return
     * @throws Exception
     */
    public static String encryptMapMD5(Map<String, Object> map) throws Exception {
        return encryptMD5(getParamStr(map));
    }

//    public static void main(String[] args) throws Exception{
//        Map<String,Object> map=getTreeMap();
//        map.put("date",DateUtils.getDateStr(new Date()));
//        map.put("key","VQXMUFKYRDYAHEVTSOQLIJIZWCWNISUAEUBEFODNKCPZIYZBPR");
//        map.put("orderNo","30005491221501761293984");
//        map.put("salt","123456");
//        map.put("cerName","tianjin_dingnuo");
//        String sin=encryptMapMD5(map);
//        System.out.println(sin);
//    }


    /**
     * UTF8加密map形式的data
     *
     * @param map
     * @return
     * @throws Exception
     */
    public static String Utf8EncryptMapMD5(Map<String, Object> map) throws Exception {
        return EncoderByMfd5(getParamStr(map));
    }

    /**
     * utf8MD5加密
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String EncoderByMfd5(String str) throws Exception {
        String result = "";
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
            // 这句是关键
            md5.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(),e);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(),e);
        }
        byte b[] = md5.digest();
        int i;
        StringBuffer buf = new StringBuffer("");
        for (int offset = 0; offset < b.length; offset++) {
            i = b[offset];
            if (i < 0)
                i += 256;
            if (i < 16)
                buf.append("0");
            buf.append(Integer.toHexString(i));
        }
        result = buf.toString();

        return result;
    }

    /**
     * utf8MD5加密
     *
     * @param str
     * @return
     * @throws Exception
     */
    public static String EncoderByMfd5(String str, int bit) {
        String md5 = "";
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes("UTF-8"));

            byte b[] = md.digest();
            int i;
            StringBuffer sb = new StringBuffer();
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0) {
                    i += 256;
                }
                if (i < 16) {
                    sb.append("0");
                }
                sb.append(Integer.toHexString(i));
            }
            md5 = sb.toString();
            if (bit == 16) {
                //截取32位md5为16位
                return md5.substring(8, 24);
            }
        } catch (NoSuchAlgorithmException e) {
            log.error(e.getMessage(),e);
        } catch (UnsupportedEncodingException e) {
            log.error(e.getMessage(),e);
        }
        // 这句是关键

        return md5;
    }

    /**
     * 综合收银台签名处理方法
     *
     * @param map
     * @return
     * @throws Exception
     */
    public static String utf8EncryptMapToMD5WithoutNullValue(Map<String, Object> map) throws Exception {
        return EncoderByMfd5(convertMapToStr(map));
    }

    public static String convertMapToStr(Map<String, Object> map) {
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        List<String> list = new ArrayList<>();
        for (Map.Entry<String, Object> next : entries) {
            String key = next.getKey();
            Object value = next.getValue();
            if ((value != null) && (value.toString().length() != 0)) {
                list.add(key + "=" + value);
            }
        }
        return String.join("&", list);
    }
}
